/*
  (C) 2007 - Boston University
  Contact: Michael Ocean 

	this file was adapted from a CS511 submission

  This work is a part of the larger snBench project.  Information
  can be found at: http://csr.bu.edu/snbench 

  This program is free software; you can redistribute it and/or
  modify it under the terms of Version 2 of the GNU General Public 
  License.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.
  
  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package stepide;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;

public class MenuFactory extends JMenuBar {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * Creates the frame menu bar.
	 * 
	 * @return the menu bar
	 */
	private MenuFactoryListener responder;
	
	private MenuFactory(){
		super();
	}
	
	public MenuFactory(MenuFactoryListener mfl) {
		super();

		responder = mfl;		
		this.add(createFileMenu());
		this.add(createEditMenu());
		this.add(createViewMenu());
		this.add(createActionMenu());
		//return menu;
	}

	/**
	 * Creates the menu for basic file operations
	 * 
	 * @return the file menu
	 */
	private JMenu createFileMenu() {
		JMenu fileMenu = new JMenu("File");
		fileMenu.setMnemonic(KeyEvent.VK_F);
		JMenuItem fileNew = new JMenuItem("New", new ImageIcon("stepide/icons/New16.gif"));
		JMenuItem fileOpen = new JMenuItem("Open...", new ImageIcon("stepide/icons/Open16.gif"));
		JMenuItem fileSave = new JMenuItem("Save", new ImageIcon("stepide/icons/Save16.gif"));
		JMenuItem fileSaveAs = new JMenuItem("Save As...", new ImageIcon("stepide/icons/SaveAs16.gif"));
		JMenuItem fileSavePng = new JMenuItem("Save PNG Image...");
		JMenuItem fileClose = new JMenuItem("Close", new ImageIcon("stepide/icons/Close16.gif"));
		JMenuItem fileExit = new JMenuItem("Exit");
		JMenuItem filePrint = new JMenuItem("Print...", new ImageIcon("stepide/icons/Print16.gif"));
		
		fileNew.setMnemonic(KeyEvent.VK_N);
		fileOpen.setMnemonic(KeyEvent.VK_O);
		fileSave.setMnemonic(KeyEvent.VK_S);
		fileSaveAs.setMnemonic(KeyEvent.VK_A);
		fileClose.setMnemonic(KeyEvent.VK_C);
		fileExit.setMnemonic(KeyEvent.VK_E);
		filePrint.setMnemonic(KeyEvent.VK_P);
		fileSavePng.setMnemonic(KeyEvent.VK_G);
		
		fileNew.setToolTipText("Create a new graph");
		fileOpen.setToolTipText("Open an existing STEP XML file");
		fileSave.setToolTipText("Saves the current graph");
		fileSaveAs.setToolTipText("Saves the current graph with a specified name");
		fileClose.setToolTipText("Closes the current graph");
		fileExit.setToolTipText("Quits the STEP Stone IDE");
		filePrint.setToolTipText("Print the current graph");
		fileSavePng.setToolTipText("Saves the current STEP Graph as a PNG image");
		
		fileNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
		fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK));
		fileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
		fileSaveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F12, ActionEvent.SHIFT_MASK));
		fileClose.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.CTRL_MASK));
		fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK));
		filePrint.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.CTRL_MASK));
		
		fileMenu.add(fileNew).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileNew(e);
			}
		});

		fileMenu.add(fileOpen).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileOpen(e);
			}
		});

		fileMenu.add(fileSave).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileSave(e);
			}
		});

		fileMenu.add(fileSaveAs).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileSaveAs(e);
			}
		});
		
		fileMenu.add(fileSavePng).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileSavePng(e);
			}
		});

		fileMenu.add(fileClose).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFileClose(e);
			}
		});

		fileMenu.addSeparator();

		fileMenu.add(filePrint).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionFilePrint(e);
			}
		});

		fileMenu.addSeparator();

		fileMenu.add(fileExit).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionQuit(e);
			}
		});

		return fileMenu;
	}

	/**
	 * Creates the menu for basic editing operations
	 * 
	 * @return the edit menu
	 */
	private JMenu createEditMenu() {
		JMenu editMenu = new JMenu("Edit");
		editMenu.setMnemonic(KeyEvent.VK_E);
		JMenuItem editUndo = new JMenuItem("Undo", new ImageIcon("stepide/icons/Undo16.gif"));
		JMenuItem editRedo = new JMenuItem("Redo", new ImageIcon("stepide/icons/Redo16.gif"));
		JMenuItem editRemove = new JMenuItem("Remove Selected Node/Edge", new ImageIcon("stepide/icons/Remove16.gif"));
		
		editUndo.setMnemonic(KeyEvent.VK_U);
		editRedo.setMnemonic(KeyEvent.VK_R);
		editRemove.setMnemonic(KeyEvent.VK_R);
		
		editUndo.setToolTipText("Undo the previous action");
		editRedo.setToolTipText("Redo the most recently undone action");
		editRemove.setToolTipText("Removes the selected node from the STEP graph");

		editUndo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
		editRedo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
		editRemove.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.CTRL_MASK));

		editMenu.add(editUndo).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionEditUndo(e);
			}
		});

		editMenu.add(editRedo).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionEditRedo(e);
			}
		});

		editMenu.addSeparator();

		editMenu.add(editRemove).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionEditRemoveSelection(e);
			}
		});

		return editMenu;
	}

	/**
	 * Creates the menu where views can be shown and focused.
	 * 
	 * @return the focus view menu
	 */
	private JMenu createActionMenu() {
		JMenu actionMenu = new JMenu("Actions");
		actionMenu.setMnemonic(KeyEvent.VK_A);
		JMenuItem validate = new JMenuItem("Validate graph...");
		JMenuItem opcode = new JMenuItem("Import Opcode...", new ImageIcon("stepide/icons/Add16.gif"));
		JMenuItem sxe = new JMenuItem("Bind to SXE...", new ImageIcon("stepide/icons/Run16.gif"));
		
		
		sxe.setToolTipText("Dispatchs the current graph to the SXE for binding");
		opcode.setToolTipText("Displays the opcode library's XML for adding new opcodes");
		validate.setToolTipText("Validates the currently constructed graph");	
		
	
		opcode.setMnemonic(KeyEvent.VK_I);
		sxe.setMnemonic(KeyEvent.VK_B);
		validate.setMnemonic(KeyEvent.VK_V);
		
		
		opcode.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.CTRL_MASK));
		sxe.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK));
		validate.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
		
			
		actionMenu.add(validate).addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				responder.doActionValidate(e);
			}
		});
			
		actionMenu.add(opcode).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionImportOpcode(e);
			}
		});

		actionMenu.add(sxe).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionBindToSxe(e);
			}
		});

		return actionMenu;
	}

	/**
	 * Creates the menu where not shown views can be shown.
	 * 
	 * @return the view menu
	 */
	private JMenu createViewMenu() {
		JMenu viewMenu = new JMenu("View");
		viewMenu.setMnemonic(KeyEvent.VK_V);
		JMenu zoomMenu = new JMenu("Zoom");
		zoomMenu.setMnemonic(KeyEvent.VK_Z);

		viewMenu.addSeparator();
		
		JMenuItem xml = new JMenuItem("Refresh XML...");
		xml.setToolTipText("Displays the XML behind the currently constructed graph");	
		xml.setMnemonic(KeyEvent.VK_X);
		xml.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK));
		viewMenu.add(xml).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionViewXml(e);
			}
		});

		JMenuItem layout = new JMenuItem("Re-Layout Graph...");
		layout.setToolTipText("Redraw the graph to optimize layout");	
		layout.setMnemonic(KeyEvent.VK_L);
		layout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, ActionEvent.CTRL_MASK));
		viewMenu.add(layout).addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionViewLayout(e);
			}
		});
		
		viewMenu.addSeparator();
				
		JMenuItem zoomIn = new JMenuItem("Zoom In", new ImageIcon("stepide/icons/ZoomIn16.png"));
		JMenuItem zoomOut = new JMenuItem("Zoom Out", new ImageIcon("stepide/icons/ZoomOut16.png"));
		
		zoomIn.setMnemonic(KeyEvent.VK_I);
		zoomOut.setMnemonic(KeyEvent.VK_O);
		
		zoomIn.setToolTipText("Zoom in by 25%");
		zoomOut.setToolTipText("Zoom out by 25%");

		zoomIn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionViewZoomIn(e);
			}
		});
		zoomOut.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				responder.doActionViewZoomOut(e);
			}
		});
		
		zoomMenu.add(zoomIn);
		zoomMenu.add(zoomOut);

		viewMenu.add(zoomMenu);

		return viewMenu;
	}
}
